<?php
// +-----------------+--------------+------+-----+---------+----------------+
// | Field           | Type         | Null | Key | Default | Extra          |
// +-----------------+--------------+------+-----+---------+----------------+
// | id              | int(11)      | NO   | PRI | NULL    | auto_increment |
// | category_id     | int(11)      | YES  |     | 0       |                |
// | name            | varchar(50)  | YES  |     |         |                |
// | title           | varchar(255) | YES  |     |         |                |
// | sort_num        | int(11)      | YES  |     | 0       |                |
// | seo_title       | varchar(255) | YES  |     |         |                |
// | seo_keywords    | varchar(255) | YES  |     |         |                |
// | seo_description | varchar(255) | YES  |     |         |                |
// | description     | varchar(255) | YES  |     |         |                |
// | content         | text         | YES  |     | NULL    |                |
// | pc_cover_id     | int(11)      | YES  |     | 0       |                |
// | wap_cover_id    | int(11)      | YES  |     | 0       |                |
// | status          | tinyint(1)   | YES  |     | 0       |                |
// | user_id         | int(11)      | YES  |     | 0       |                |
// | create_time     | int(11)      | YES  |     | 0       |                |
// | update_time     | int(11)      | YES  |     | 0       |                |
// | video_url       | varchar(255) | YES  |     |         |                |
// | star_up         | int(11)      | YES  |     | 0       |                |
// | is_origin       | tinyint(1)   | YES  |     | 0       |                |
// | origin_author   | varchar(100) | YES  |     |         |                |
// | take_weather    | varchar(255) | YES  |     |         |                |
// | take_time       | varchar(255) | YES  |     |         |                |
// | take_material   | varchar(255) | YES  |     |         |                |
// | take_tool       | varchar(255) | YES  |     |         |                |
// | buy_url         | varchar(255) | YES  |     |         |                |
// | star_down       | int(11)      | YES  |     | 0       |                |
// +-----------------+--------------+------+-----+---------+----------------+
namespace app\common\model;
use think\Loader;
use think\Config;
use think\Db;
use app\common\model\Tag;
use app\common\model\StarLog;
class Article extends Base{
  protected $auto = ['user_id'];

  public function createOrUpdate($data){
    $res = ["status" => false, "msg" => "文章保存失败"];

    if(isset($data["id"])){
      $user = login_user();
      $this->where("id", $data["id"]);
      if(empty($user)){
        $res["msg"] = "编辑用户不存在";
        return $res;
      }else if($user["user_type"] != "manager"){
        $this->where("user_id", $user["id"]);
      }
      if(!$this->count()){
        $res["msg"] = "您没有权限编辑该文章";
        return $res;
      }
    }

    $validate = Loader::validate("Article");
    if($validate->check($data)){
      $this->allowField(true);
      if(empty($data["id"])){
        $this->save($data);
        $id = $this->id;
        // 用户为自已创建的作品自动点赞
        $star_data = [
          "star_type" => "up",
          "related_type" => "Article",
          "related_id" => $id,
        ];
        $starModel = new StarLog();
        $star_res = $starModel->createItem($star_data);
      }else{
        $this->isUpdate(true)->save($data);
        $id = $data["id"];
      }
      $tagModel = new Tag();
      $tagModel->taggble("Article", $id, $data["tag_names"]);
      $res = ["status" => true, "msg" => "文章保存成功"];
    }else{
      $res["msg"] = $validate->getError();
    }
    return $res;
  }

  /**
   * 关联查询单条记录详细信息
   * @Author zhanghong
   * @Date   2017-05-04
   * @param  string     $type        关联对象类型
   * @param  string     $id          Article ID
   * @param  array      $option      扩展参数
   * @return array                   Article Item
   */
  public function relatedRead($type, $id, $option = []){
    $prefix = Config::get("database.prefix");
    $this->join("{$prefix}user", "{$prefix}user.id={$prefix}article.user_id", "LEFT")
         ->join("{$prefix}upload wap_upload", "{$prefix}article.wap_cover_id={$prefix}upload.id", "LEFT")
         ->join("{$prefix}category", "{$prefix}article.category_id={$prefix}category.id", "LEFT");

    $select_fields = ["{$prefix}article.*"];
    array_push($select_fields, "{$prefix}user.nickname AS user_nickname");
    array_push($select_fields, "{$prefix}user.avatar AS user_avatar");
    array_push($select_fields, "{$prefix}user.description AS user_description");
    array_push($select_fields, "wap_upload.save_path AS wap_cover_path");
    array_push($select_fields, "{$prefix}category.title AS category_title");
    $this->field($select_fields);

    $this->where("type", $type)->where("{$prefix}article.id", $id);

    $item = $this->find();

    if(empty($item) || $item["status"] > 0){
      return $item;
    }

    // 当前用户可以查看自己的草稿文档
    // 或者知道草稿文档的创建时间
    $user_id = login_user_id();
    $create_time = 0;
    if(isset($option["create_time"]) && !empty($option["create_time"])){
      $create_time = intval($option["create_time"]);
    }
    if($item["user_id"] != $user_id && $item["create_time"] != $option["create_time"]){
      $item = null;
    }

    return $item;
  }

  /**
   * 查询方法
   * @Author zhanghong
   * @Date   2017-01-20
   * @param  [array]      $param     查询参数
   * @param  integer      $page_rows 每页显示的记录数
   * @return \think\paginator\Collection 
   */
  public function managerSelect($param, $page_rows = 15){
    $prefix = Config::get("database.prefix");
    
    $allow_param = array_merge($param, ["query_mode" => "manager"]);

    $this->searchWhere($allow_param)
         ->join("{$prefix}user", "{$prefix}user.id={$prefix}article.user_id", "LEFT")
         ->join("{$prefix}tagged", "{$prefix}tagged.taggable_type='Article' AND {$prefix}tagged.taggable_id={$prefix}article.id", "LEFT")
         ->join("{$prefix}upload wap_upload", "{$prefix}article.wap_cover_id={$prefix}upload.id", "LEFT");

    $options = $this->getOptions();
    $bind    = $this->getBind();
    $total_count = $this->count("DISTINCT {$prefix}article.id");

    $select_fields = [];
    $article_fields = ["id", "name", "title", "description", "update_time", "create_time", "status", "user_id"];
    foreach ($article_fields as $idx => $key) {
      array_push($select_fields, "{$prefix}article.{$key}");
    }
    array_push($select_fields, "IF(video_url IS NULL, 0, LENGTH(video_url)) AS is_has_video");
    array_push($select_fields, "{$prefix}user.nickname AS user_nickname");
    array_push($select_fields, "{$prefix}user.avatar AS user_avatar");
    array_push($select_fields, "wap_upload.save_path AS wap_cover_path");
    array_push($select_fields, "IF({$prefix}article.star_up=0 AND {$prefix}article.star_down=0, 0, ({$prefix}article.star_up-{$prefix}article.star_down)/({$prefix}article.star_up+{$prefix}article.star_down)) AS star_sorce");
    
    $sort_type = "";
    if(isset($param["sort_type"])){
      $sort_type = $param["sort_type"];
    }
    $order_str = $this->queryOrderStr($sort_type);

    // 需要把TP框架Query里的optoins方法改成public方法
    $this->options($options)->bind($bind)->field($select_fields)
    ->group("{$prefix}article.id")->order($order_str);

    $config["query"] = ["query" => $param];
    // 分页参数名是 page ，paginate方法内有获取到该值的方法
    $page = 1;
    if(isset($param["page"])){
      $page = intval($param["page"]);
    }
    $config["page"] = $page;
    $paginate = $this->paginate($page_rows, $total_count, $config);
    return $paginate;
  }

  /**
   * 前台用户查询方法
   * @Author zhanghong
   * @Date   2017-02-15
   * @param  [array]      $param     查询参数
   * @param  integer      $page_rows 每页显示的记录数
   * @return \think\paginator\Collection 
   */
  public function memberSelect($param, $page_rows = 15){
    $prefix = Config::get("database.prefix");

    // 过滤掉不允许前台用户查询的字段
    $allow_param = [];
    $allow_param_names = array("keyword", "tag_id", "category_id", "personal", "status", "user_id", "type");
    foreach ($allow_param_names as $name) {
      if(isset($param[$name]) && !empty($param[$name])){
        $allow_param[$name] = $param[$name];
      }
    }
    $allow_param["query_mode"] = "member";

    $this->searchWhere($allow_param)
         ->join("{$prefix}user", "{$prefix}user.id={$prefix}article.user_id", "LEFT")
         ->join("{$prefix}tagged", "{$prefix}tagged.taggable_type='Article' AND {$prefix}tagged.taggable_id={$prefix}article.id", "LEFT")
         ->join("{$prefix}upload wap_upload", "{$prefix}article.wap_cover_id={$prefix}upload.id", "LEFT");

    $options = $this->getOptions();
    $bind    = $this->getBind();
    $total_count = $this->count("DISTINCT {$prefix}article.id");

    $select_fields = [];
    $article_fields = ["id", "name", "title", "description", "update_time", "create_time", "status", "user_id"];
    foreach ($article_fields as $idx => $key) {
      array_push($select_fields, "{$prefix}article.{$key}");
    }
    array_push($select_fields, "IF(video_url IS NULL, 0, LENGTH(video_url)) AS is_has_video");
    array_push($select_fields, "{$prefix}user.nickname AS user_nickname");
    array_push($select_fields, "{$prefix}user.avatar AS user_avatar");
    array_push($select_fields, "wap_upload.save_path AS wap_cover_path");
    array_push($select_fields, "IF({$prefix}article.star_up=0 AND {$prefix}article.star_down=0, 0, ({$prefix}article.star_up-{$prefix}article.star_down)/({$prefix}article.star_up+{$prefix}article.star_down)) AS star_sorce");  

    $sort_type = "";
    if(isset($param["sort_type"])){
      $sort_type = $param["sort_type"];
    }
    $order_str = $this->queryOrderStr($sort_type);

    $this->options($options)->bind($bind)->field($select_fields)
          ->group("{$prefix}article.id")->order($order_str);

    $config["query"] = ["query" => $param];
    // 分页参数名是 page ，paginate方法内有获取到该值的方法
    $page = 1;
    if(isset($param["page"])){
      $page = intval($param["page"]);
    }
    $config["page"] = $page;
    $paginate = $this->paginate($page_rows, $total_count, $config);
    return $paginate;
  }

    /**
   * 相同作者的最新作品
   * @Author zhanghong
   * @Date   2017-03-05
   * @param  [type]     $user_id [description]
   * @param  integer    $id      [description]
   * @return [type]              [description]
   */
  public function sameAuthorList($id, $user_id = 0, $limit = 4){
    if(empty($user_id)){
      $user_id = $this->where("id", $id)->column("user_id");
    }
    
    $prefix = Config::get("database.prefix");
    $this->where("{$prefix}article.user_id", $user_id)->where("{$prefix}article.status", true);

    $this->join("{$prefix}upload wap_upload", "{$prefix}article.wap_cover_id={$prefix}upload.id", "LEFT");

    $select_fields = [];
    $article_fields = ["id", "name", "title", "description", "update_time", "create_time", "status", "user_id"];
    foreach ($article_fields as $idx => $key) {
      array_push($select_fields, "{$prefix}article.{$key}");
    }
    array_push($select_fields, "wap_upload.save_path AS wap_cover_path");
    $list = $this->field($select_fields)->group("{$prefix}article.id")->order("IF({$prefix}article.id={$id}, 1, 0), {$prefix}article.id DESC")->limit($limit)->select();
    return $list;
  }

  /**
   * 网站首页最新Article
   * @Author zhanghong
   * @Date   2017-05-01
   * @param  string     $type        文章类型
   * @param  integer    $limit_count [description]
   * @return [type]                  [description]
   */
  public function topTypeList($type, $limit_count = 8){
    $prefix = Config::get("database.prefix");

    $select_fields = [];
    $article_fields = ["id", "name", "title", "description", "update_time", "create_time", "status", "user_id"];
    foreach ($article_fields as $idx => $key) {
      array_push($select_fields, "{$prefix}article.{$key}");
    }
    array_push($select_fields, "IF(video_url IS NULL, 0, LENGTH(video_url)) AS is_has_video");
    array_push($select_fields, "{$prefix}user.nickname AS user_nickname");
    array_push($select_fields, "{$prefix}user.avatar AS user_avatar");
    array_push($select_fields, "wap_upload.save_path AS wap_cover_path");
    array_push($select_fields, "IF({$prefix}article.star_up=0 AND {$prefix}article.star_down=0, 0, ({$prefix}article.star_up-{$prefix}article.star_down)/({$prefix}article.star_up+{$prefix}article.star_down)) AS star_sorce");

    $param = ["query_mode" => "member", "type" => $type];
    $order_str = $this->queryOrderStr("time_desc");

    $list =  $this->searchWhere($param)->field($select_fields)
                   ->join("{$prefix}user", "{$prefix}user.id={$prefix}article.user_id", "LEFT")
                   ->join("{$prefix}tagged", "{$prefix}tagged.taggable_type='Article' AND {$prefix}tagged.taggable_id={$prefix}article.id", "LEFT")
                   ->join("{$prefix}upload wap_upload", "{$prefix}article.wap_cover_id={$prefix}upload.id", "LEFT")
                   ->group("{$prefix}article.id")
                   ->order($order_str)
                   ->limit($limit_count)
                   ->select();
    return $list;
  }

  /**
   * 查询语句的排序方式
   * @Author zhanghong
   * @Date   2017-05-04
   * @param  [type]     $sort_type [description]
   * @return [type]                [description]
   */
  private function queryOrderStr($sort_type = ""){
    $prefix = Config::get("database.prefix");
    switch ($sort_type) {
    case "time_desc":
      $order_str = "{$prefix}article.id DESC";
      break;
    default:
      $order_str = "star_sorce DESC, {$prefix}article.star_up DESC, {$prefix}article.id DESC";
      break;
    }
    return $order_str;
  }

  /**
   * 生成搜索条件
   * @Author zhanghong
   * @Date   2017-04-12
   * @param    array      $param 请求参数
   * @return   array             Select Map
   */
  private function searchWhere($param){
    $prefix = Config::get("database.prefix");
    if(!isset($param["type"]) || empty($param["type"])){
      $param["type"] = "empty";
    }
    foreach ($param as $key => $value) {
      if(empty($value)){
        continue;
      }
      switch ($key) {
      case "keyword":
        if(empty($value)){
          continue;
        }else{
          $keyword = "%{$value}%";
        }
        $this->where("{$prefix}article.title", "like", $keyword);
        break;
      case "type":
        $this->where("{$prefix}article.{$key}", $value);
        break;
      case "user_id":
      case "category_id":
        $value = intval($value);
        if($value > 0){
          // $map["{$prefix}tagged.{$key}"] = intval($value);
          $this->where("{$prefix}article.{$key}", $value);
        }
        break;
      case "user_name":
        if(empty($value)){
          continue;
        }else{
          $keyword = "%{$value}%";
        }
        $this->where("{$prefix}user.name|{$prefix}user.nickname|{$prefix}user.mobile", "like", $keyword);
        break;
      case "tag_id":
        $value = intval($value);
        if($value > 0){
          $this->where("{$prefix}tagged.tag_id", $value);
        }
        break;
      }
    }

    if(isset($param["personal"]) && $param["personal"] == true){
      // 当personal时是个人中心，列出自己的所有article(包含status=false的)
      if(isset($param["status"])){
        $int_status = intval($param["status"]);
        if($int_status < 1){
          $int_status = 0; 
        }else{
          $int_status = 1;
        }
        $this->where("{$prefix}article.status", $int_status);
      }
      $current_user_id = login_user_id();
      $this->where("{$prefix}article.user_id", $current_user_id);
    }else{
      if(!isset($param["query_mode"])){
        $param["query_mode"] = "member";
      }
      if($param["query_mode"] != "manager"){
        // 非个人用户并且不是管理员，只列表所有status=true的
        $this->where("{$prefix}article.status", true);
      }
    }
    return $this;
  }
}